package com.service.admin.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.service.admin.member.service.MemberService;
import com.service.admin.member.service.MemberStoreService;
import com.service.admin.order.controller.rep.OrderHrComboPageRep;
import com.service.admin.order.controller.req.OrderHrComboPageReq;
import com.service.admin.order.controller.req.OrderReq;
import com.service.admin.order.service.OrderProductHrComboDetailsService;
import com.service.admin.order.service.OrderProductHrComboService;
import com.service.admin.product.service.ProductHrComboService;
import com.service.admin.support.Language;
import com.service.admin.utils.I18nUtil;
import com.service.core.exception.CommonException;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.enums.CoinsEnum;
import com.service.dao.enums.HashRateOrderEnums;
import com.service.dao.enums.MemberJAType;
import com.service.dao.mapper.OrderProductHrComboMapper;
import com.service.dao.model.*;
import com.service.utility.common.MathUtil;
import com.service.utility.common.UUIDUtil;
import com.service.utility.modelmapper.ModelMapperUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


@Service("hashRateOrderService")
public class OrderProductHrComboServiceImpl extends ServiceImpl<OrderProductHrComboMapper, OrderProductHrCombo> implements OrderProductHrComboService {

    @Autowired
    private OrderProductHrComboDetailsService orderProductHrComboDetailsService;

    @Autowired
    private ProductHrComboService productHrComboService;

    @Autowired
    private MemberStoreService memberStoreService;

    @Autowired
    private MemberService memberService;

    @Autowired
    private OrderProductHrComboMapper orderProductHrComboMapper;

    @Value("${productHrComboOrderPrefix}")
    private String productOtherOrderPrefix;


    @Override
    public CommonPageRep pageOrder(OrderHrComboPageReq pageReq) {
        Page<OrderProductHrCombo> page = PageHelper.startPage(pageReq.getPageNo(), pageReq.getPageSize());
        LambdaQueryWrapper<OrderProductHrCombo> queryWrapper = new QueryWrapper<OrderProductHrCombo>().lambda();
        if (!ObjectUtils.isEmpty(pageReq.getOrderStatus())) {
            queryWrapper.eq(OrderProductHrCombo::getOrderStatus, pageReq.getOrderStatus());
        }
        if (!ObjectUtils.isEmpty(pageReq.getStartTime())) {
            queryWrapper.ge(OrderProductHrCombo::getCreateTime, pageReq.getStartTime());
        }
        if (!ObjectUtils.isEmpty(pageReq.getEndTime())) {
            queryWrapper.le(OrderProductHrCombo::getCreateTime, pageReq.getEndTime());
        }
        if (StringUtils.isNotBlank(pageReq.getMemberAccount())) {
            queryWrapper.like(OrderProductHrCombo::getMemberAccount, pageReq.getMemberAccount());
        }
        queryWrapper.orderByDesc(OrderProductHrCombo::getCreateTime);
        baseMapper.selectList(queryWrapper);
        List<OrderHrComboPageRep> resultList = page.getResult().stream().map(item -> {
            OrderHrComboPageRep pageRep = ModelMapperUtil.getStrictModelMapper().map(item, OrderHrComboPageRep.class);
            pageRep.setDetailsList(orderProductHrComboDetailsService.getOrderHrComboDetailsByOrderId(item.getId()));
            return pageRep;
        }).collect(Collectors.toList());

        return CommonPageRep.buildResultRep(page, resultList);
    }

    @Override
    public OrderHrComboPageRep getOrderDetail(Integer orderId) {
        OrderProductHrCombo orderProductHrCombo = baseMapper.selectById(orderId);
        if (ObjectUtils.isEmpty(orderProductHrCombo)) {
            throw new CommonException("订单不存在");
        }
        OrderHrComboPageRep hrComboRep = ModelMapperUtil.getStrictModelMapper().map(orderProductHrCombo, OrderHrComboPageRep.class);
        hrComboRep.setDetailsList(orderProductHrComboDetailsService.getOrderHrComboDetailsByOrderId(orderId));
        return hrComboRep;
    }

    @Override
    public BigDecimal totalEffectiveOrderByMemberListAndTime(List<Integer> memberIds, Date startTime, Date endTime) {
        List<Integer> orderStatus = HashRateOrderEnums.getHrComboUsingStatus();
        List<Integer> orderSource = HashRateOrderEnums.listEffectiveOrderSource();
        return baseMapper.totalEffectiveOrderMoneyByMemberIdsAndStatusAndSourceListAndTime(memberIds, orderStatus, orderSource, startTime, endTime);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean create(OrderReq orderReq, ProductHrCombo combo, Member member, MemberStore memberStore) {

        if (combo.getMinBuyNum() > orderReq.getNum()) {
            throw new CommonException("购买数量少于起购数量", "order_num_less_then");
        }
        if (combo.getStock() >= 0 && orderReq.getNum() > combo.getStock()) {
            throw new CommonException("算力套餐库存不足", "hash_rate_combo_stock_is_deficiency");
        }
        if (!ObjectUtils.isEmpty(combo.getLimitBuyNum()) && combo.getLimitBuyNum() > 0 && orderReq.getNum() > combo.getLimitBuyNum()) {
            throw new CommonException(I18nUtil.getMessage("out_of_limit_buy", Language.LANG.get(), combo.getLimitBuyNum()));
        }
        BigDecimal orderMoney = combo.getComboPrice().multiply(new BigDecimal(orderReq.getNum()));

        if (memberStore.getNum().compareTo(orderMoney) < 0) {
            throw new CommonException("会员余额不足", "store_balance_not_enough");
        }

        Date currentDate = new Date();
        OrderProductHrCombo orderProductHrCombo = new OrderProductHrCombo();
        orderProductHrCombo.setOrderType(combo.getComboType());
        orderProductHrCombo.setHrOrderNo(buildShopOrderNo());
        orderProductHrCombo.setMemberId(member.getId());
        orderProductHrCombo.setMemberAccount(member.getUserAccount());
        orderProductHrCombo.setTotalComboNum(orderReq.getNum());
        orderProductHrCombo.setTotalHashRate(MathUtil.mul(combo.getComputingPower(), orderReq.getNum()));
        orderProductHrCombo.setOrderMoney(orderMoney);
        orderProductHrCombo.setPayMoney(orderMoney);
        orderProductHrCombo.setPayTypeGroup(CoinsEnum.USDT.getCode());//USDT
        orderProductHrCombo.setPayTime(currentDate);
        orderProductHrCombo.setOrderStatus(HashRateOrderEnums.Status.payed.getCode());
        orderProductHrCombo.setCreateTime(currentDate);
        orderProductHrCombo.setCustodyFee(combo.getCustodyFee());
        orderProductHrCombo.setStartTime(com.service.admin.utils.DateUtils.changeDateTo3point(DateUtils.addDays(new Date(), combo.getPackageDays() + 1)));
        orderProductHrCombo.setEndTime(hrComboIntervalDate(combo));
        int orderId = baseMapper.insert(orderProductHrCombo);
        orderProductHrComboDetailsService.createOrderDetail(combo, orderReq.getNum(), orderProductHrCombo);

        //减扣会员余额
        memberStoreService.payByMemberStore(member.getId(), CoinsEnum.USDT.getName(), MemberJAType.PAY_HR_COMBO, orderMoney, orderId);

        productHrComboService.updateProductStockNum(combo.getId(), orderReq.getNum());
        return true;
    }

    @Override
    public BigDecimal totalStatementByParam(String someDay, List<Integer> orderStatus) {
        return orderProductHrComboMapper.totalStatementByParam(someDay, orderStatus);

    }

    /**
     * 获取订单到期时间
     *
     * @param combo
     * @return
     */
    private Date hrComboIntervalDate(ProductHrCombo combo) {
        Date tomorrow = DateUtils.addDays(new Date(), combo.getPackageDays() + 1);
        OrderProductHrComboDetails update = new OrderProductHrComboDetails();
        if (!ObjectUtils.isEmpty(combo)) {
//            Date startDate = DateUtil.nDaysAfterDate(productHrCombo.getPackageDays());
            update.setStartTime(com.service.admin.utils.DateUtils.changeDateTo3point(tomorrow));
            return com.service.admin.utils.DateUtils.changeDateTo3point(DateUtils.addDays(tomorrow, combo.getDeadline()));
        } else {
//            Date startDate = DateUtil.nDaysAfterDate(1);
//            update.setStartTime(com.service.admin.utils.DateUtils.changeDateTo3point(tomorrow));
            return com.service.admin.utils.DateUtils.changeDateTo3point(DateUtils.addDays(tomorrow, combo.getDeadline()));
        }
    }

    private String buildShopOrderNo() {
        String no = productOtherOrderPrefix + DateFormatUtils.format(new Date(), "yyyyMMdd") + UUIDUtil.randomUUID10().substring(0, 8);
        OrderProductHrCombo orderList = getOne(new QueryWrapper<OrderProductHrCombo>().lambda()
                .eq(OrderProductHrCombo::getHrOrderNo, no).last(" limit 1"));
        if (!ObjectUtils.isEmpty(orderList)) {
            no = buildShopOrderNo();
        }
        return no;
    }
}
